#pragma once 

#include "Socket.hpp"
#include <memory>
#include <functional>
#include <sys/types.h>
#include <sys/wait.h>
using namespace MySocketModule;

using tcpHandle_t = function<bool (SockPtr,InetAddr)>;  //上层传递的处理任务的函数

class TcpServer
{
private:
    unique_ptr<Socket> _listenSocket;
    int _port;
    bool _isRunning;
    tcpHandle_t _handle;
public:
    TcpServer(int port)
        :_listenSocket(make_unique<TcpSocket>())       //一定是tcpSocket对象
        ,_isRunning(false)
        ,_port(port)
    {
    }

    void InitTcpServer(tcpHandle_t handle)
    {
        _handle = handle;
        //一瞬间，tcp建立等相关内容都有了
        //tcpSocket对象，调用tcp响应的方法
        _listenSocket->BuildTcpSocketMethod(_port);    
    }


    void Loop()
    {
        _isRunning = true;
        while(_isRunning)
        {
            //  1.accept
            InetAddr clientAddr;
            auto sockfd = _listenSocket->AcceptOrDie(&clientAddr);  //接收请求
            if(sockfd == nullptr)
                continue;
            //  2.交给上层，进行IO处理
            LOG(LogGrade::NORMAL) << "get a new client: " << clientAddr.getInfo();   //打印客户端的ip+port

            //可以直接让tcp进行IO了
            // sockfd->Recv();
            // sockfd->Send();

            pid_t pid = fork();
            if(pid == 0)
            {
                _listenSocket->Close();     //子进程不需要拉客
                if(fork() > 0)
                    exit(0);
                //孙子进程处理
                _handle(sockfd,clientAddr);
                exit(0);
            }
            sockfd->Close();    //父进程不需要服务员的fd
            waitpid(pid,nullptr,0);
        }
        _isRunning = false;
    }

    ~TcpServer()
    {
        _listenSocket->Close();
    }
};
